const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

class MyPromise {
  constructor(executor) {
    // 捕获执行器错误
    try{
      executor(this.resolve, this.reject)
    }catch(e) {
      this.reject(e)
    }
  }
  // promise 状态
  status = PENDING;
  // 存储成功之后的返回值
  value = undefined;
  // 存储失败之后的返回值
  result = undefined;
  // then接收的成功回调
  successCallBack = []; // 解决链式调用改为数组
  // then接收的失败回调
  failCallBack = [];

  resolve = value => {
    // 如果状态不是PENDING，就结束任务
    if (this.status !== PENDING) return;
    // 改变状态为FULFILLED
    this.status = FULFILLED;
    // 存储成功的返回值
    this.value = value;
    
    // 判断，如果存在成功的回调函数则应该调用
    // this.successCallBack && this.successCallBack(this.value)
    while (this.successCallBack.length) this.successCallBack.shift()()
  }
  reject = result => {
    // 如果状态不是PENDING，就结束任务
    if (this.status !== PENDING) return;
    // 改变状态为REJECTED
    this.status = REJECTED;
    // 存储失败之后的返回值
    this.result = result;

    // 判断，如果存在错误的回调函数则应该调用
    // this.failCallBack && this.failCallBack(this.result)
    while(this.failCallBack.length) this.failCallBack.shift()()
  }

  then (successCallBack, failCallBack) {
    // 判断是否有参数
    successCallBack = successCallBack ? successCallBack : value => value;
    failCallBack = failCallBack ? failCallBack : result => { throw result };
    // then返回一个Promise对象
    let promise2 = new MyPromise((resolve, reject) => {
      // 传入一个执行器、执行器是立即执行
      // 判断状态，如果成功调用 successCallBack 如果失败调用 failCallBack
      if (this.status === FULFILLED) {
        // 变成异步代码
        setTimeout(() => {
          // 捕获回调错误
          try{
            // 状态为PENDING
            let x = successCallBack(this.value)
            // 判断 x 的值是普通值还是promise对象
            // 如果是普通值 直接调用resolve 
            // 如果是promise对象 查看promsie对象返回的结果 
            // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
            // resolve(x); // 把成功的回调返回给下一个then
            resolvePromise(promise2, x, resolve, reject)
          }catch(e) {
            reject(e)
          }
        }, 0)
      }
      else if (this.status === REJECTED) {
        setTimeout(() => {
          // 捕获回调错误
          try{
            // 状态为REJECTED
            let x = failCallBack(this.result)
            // 判断 x 的值是普通值还是promise对象
            // 如果是普通值 直接调用resolve 
            // 如果是promise对象 查看promsie对象返回的结果 
            // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
            // resolve(x); // 把成功的回调返回给下一个then
            resolvePromise(promise2, x, resolve, reject)
          }catch(e) {
            reject(e)
          }
        }, 0)
      }
      else {
        // 状态为PENDING，即异步情况
        // 此时应该存储起来两个回调函数，当同步代码执行完毕之后再调用
        // this.successCallBack = successCallBack;
        // this.failCallBack = failCallBack;
        this.successCallBack.push(() => {
          // 变成异步代码
          setTimeout(() => {
            // 捕获回调错误
            try{
              // 状态为PENDING
              let x = successCallBack(this.value)
              // 判断 x 的值是普通值还是promise对象
              // 如果是普通值 直接调用resolve 
              // 如果是promise对象 查看promsie对象返回的结果 
              // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
              // resolve(x); // 把成功的回调返回给下一个then
              resolvePromise(promise2, x, resolve, reject)
            }catch(e) {
              reject(e)
            }
          }, 0)
        });
        this.failCallBack.push(() => {
          setTimeout(() => {
            // 捕获回调错误
            try{
              // 状态为REJECTED
              let x = failCallBack(this.result)
              // 判断 x 的值是普通值还是promise对象
              // 如果是普通值 直接调用resolve 
              // 如果是promise对象 查看promsie对象返回的结果 
              // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
              // resolve(x); // 把成功的回调返回给下一个then
              resolvePromise(promise2, x, resolve, reject)
            }catch(e) {
              reject(e)
            }
          }, 0)
        });
      }
    })
    return promise2
  }

  finally (callback) {
    return this.then(value => {
      return MyPromise.resolve(callback()).then(value => value)
    }, result => {
      return MyPromise.resolve(callback()).then(() => { throw result })
    })
  }

  catch (failCallBack) {
    return this.then(undefined, failCallBack)
  }

  static all (array) {
    // all 是一个静态方法
    // all 是一个promise对象
    let res = [];
    let index = 0; // 确保所有的异步操作都完成
    return new MyPromise((resolve, reject) => {
      function addData (key, value) {
        res[key] = value;
        index++ ;
        if (index === array.length) resolve(res);
      }
      for (let i = 0;  i < array.length; i++) {
        let current = array[i];
        if (current instanceof MyPromise) {
          // promise 对象
          current.then(value => addData(i, value), result => reject(result))
        } else {
          // 普通值
          addData(i, array[i])
        }
      }
    })
  }

  static resolve(value) {
    // 把给定的值转换成promise对象
    if (value instanceof MyPromise) {
      // 是一个promise对象， 直接返回
      return value;
    } else {
      // 普通值，创建一个promise对象将值传递下去
      return new MyPromise(resolve => resolve(value))
    }
  }
}

function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    // 自己返回自己的情况
    return reject('promise2 === x => error')
  }
  if (x instanceof MyPromise) {
    // x 是promise对象
    x.then(value => resolve(value), result => reject(result))
  } else {
    // x 是普通值
    resolve(x);
  }
}

module.exports = MyPromise;